package com.appcheck.recording.handler.impl;

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.webkit.WebView;
import android.widget.AbsListView;

import com.appcheck.recording.ListenerManager;
import com.appcheck.recording.WidgetHelper;
import com.appcheck.recording.action.impl.ClickAction;
import com.appcheck.recording.action.impl.TouchAction;
import com.appcheck.recording.handler.action.DragAction;
import com.appcheck.recording.handler.action.GestureAction;
import com.appcheck.recording.handler.action.Point;
import com.appcheck.recording.utils.DisplaySizeManager;
import com.appcheck.recording.utils.Logger;

public class TouchGrouper extends Grouper {

	private List<TouchAction> actionList;
	private ArrayList<Point> pointList;
	private Double historicalDist;
	private Double headTailDist;
	
	public TouchGrouper(Grouper paramGrouper) {
		super(paramGrouper);
		this.actionList = new ArrayList();
	}

	private void clean(){
		this.actionList.clear();
		this.historicalDist = null;
		this.headTailDist = null;
		this.pointList = null;
	}
	public final boolean visit(TouchAction action){
		//Logger.INFO("Action code" + action.getActionCode());
		this.actionList.add(action);
	    if (action.getActionCode() == android.view.MotionEvent.ACTION_DOWN){
	    	//Logger.INFO("ACTION_DOWN: " + action.getX() + " " + action.getY() + " in view" + action.getView().toString());
	    	if (this.actionList.size() > 1) {
	    		this.actionList.remove(0);
	    	}
	    	ListenerManager.getListenerManager().clean();
	    }else if(action.getActionCode() == android.view.MotionEvent.ACTION_CANCEL){
	    	//Logger.INFO("ACTION_CANCEL: " + action.getX() + " " + action.getY());
	    	clean();
	    }else if((action.getActionCode() == android.view.MotionEvent.ACTION_UP) && (this.actionList.size() > 1)){
	    	//Logger.INFO("ACTION_UP: " + action.getX() + " " + action.getY() + " in view" + action.getView().toString());
	    	TouchAction firstAction = this.actionList.get(0);
	    	//如果移动的总距离小于0.03*屏幕的对角线长度，则条件为1，否则检查历史action列表中action的时间跨度，如果小于一定值，并且列表长度小于5，则条件为1
	    	if (((this.historicalDist = this.calcDist(this.actionList)).doubleValue() < 
	    			0.03D * (int)Math.sqrt(DisplaySizeManager.getWidth() * DisplaySizeManager.getWidth() + DisplaySizeManager.getHeight() * DisplaySizeManager.getHeight()) 
	    			? 1 : ((this.actionList.get(this.actionList.size() - 1).getCatchTime() - this.actionList.get(0).getCatchTime() < 120L) || this.actionList.size() <= 5) ? 1 : 0) != 0){
	    		int i;
	    		//查找WidgetHelper里面的View类型是否有当前view的父类，如果有则返回其key,注意最后检查的是View本身，View的key是0，也就是说前面都不是的话，最后才返回0，这里检查如果没有具体View是当前View的父类，并且当前View不能被点击
	    		if ( (i = WidgetHelper.getWidgetMapIndexOfView(action.getView())) == 0 && (!action.getView().isClickable())){
	    			action.setTouchTime((int)(action.getCatchTime() - firstAction.getCatchTime()));
	    			
	    			forwardActionToPlugin(action);
	    		}else if(i == 2){//如果view是EditText的子类
	    			ClickAction clickAction = new ClickAction();
	    			clickAction.setViewType(2);
	    			clickAction.setResourceName(WidgetHelper.getResourceName(action.getView()));
	    			clickAction.setText(WidgetHelper.getViewContent(action.getView()));
	    			if(action.getPreViewArray() != null){
	    				clickAction.setPreViewArray(action.getPreViewArray());
	    				clickAction.setIndex(action.getIndex());
	    			}
//	    			if(clickAction.getResourceName() == null) {
//	    				clickAction.setIndex(WidgetHelper.getCurrentIndexOfView(action.getView()));
//	    			}
	    			forwardActionToPlugin(clickAction);
	    		}
	    		//Logger.INFO(String.valueOf(i));
	    	}else{
	    		View tempObj = this.actionList.get(this.actionList.size() - 1).getView();
	    		//先判断历史Action列表长度是否超过5，如果不是则判断最后一个Action对应的View是否可以点击，并且是否不是WebView，或者是AbsListView，满足返回1，如果不满足则判断是不是当前Action的坐标超过了屏幕大小，如果是则返回1，不是返回0
	    		if ((this.actionList.size() > 5 ? 1: 
	    			((tempObj.isClickable() && (!(tempObj instanceof WebView)) || (tempObj instanceof AbsListView)) ? 0 : 
	    				 (outOfScreen(action, tempObj) ? 1 : 0))) != 0){
	    			 this.headTailDist = Double.valueOf(calcDist(firstAction.getX(), firstAction.getY(), action.getX(), action.getY()));
	    			 if(this.historicalDist == null){
	    				 this.historicalDist = calcDist(this.actionList);
	    			 }
	    			 new StringBuilder("Drag distance: ").append(this.historicalDist).toString();
	    	         new StringBuilder("Real distance: ").append(this.headTailDist).toString();
	    	         if((this.historicalDist.doubleValue() - this.headTailDist.doubleValue()) / this.headTailDist.doubleValue() < 0.12D){
	    	        	 DragAction dragAction = new DragAction();
	    	        	 dragAction.setStepsCount(this.actionList.size());
	    	        	 dragAction.setDragTime((int)(action.getCatchTime() - firstAction.getCatchTime()));
	    	        	 dragAction.setFromX(firstAction.getX());
	    	        	 dragAction.setFromY(firstAction.getY());
	    	        	 dragAction.setToX(action.getX());
	    	        	 dragAction.setToY(action.getY());
	    	        	 forwardActionToPlugin(dragAction);
	    	         }else{
	    	        	 GestureAction gestureAction = new GestureAction();
	    	        	 gestureAction.setDragTime((int)(action.getCatchTime() - firstAction.getCatchTime()));
	    	        	 gestureAction.setPoints(this.pointList);
	    	        	 forwardActionToPlugin(gestureAction);
	    	         }
	    	         ListenerManager.getListenerManager().setFlagTrue();
	    		}
	    	}
	    	clean();
	    }
	    else if((action.getActionCode() == android.view.MotionEvent.ACTION_UP) && (this.actionList.size() <= 1)){
	    	clean();
	    }
	    return true;
	}
	private boolean outOfScreen(TouchAction action, View view){
		if((action.getX() < 0.0F) || (action.getY() < 0.0F) || (action.getX() > view.getWidth()) || (action.getY() > view.getHeight())) return true;
		return false;
	}
	
	public Double calcDist(List<TouchAction> paramList){
		this.pointList = new ArrayList<Point>();
		Point formerPoint = null;
		double dist = 0.0D;
		for(TouchAction pointer: paramList){
			Point point = new Point(pointer.getX(), pointer.getY());
			this.pointList.add(point);
			if(formerPoint != null){
				dist += calcDist(point.getX(), point.getY(), formerPoint.getX(), formerPoint.getY());
			}
			formerPoint = point;
		}
		return Double.valueOf(dist);
	}
	
	public static double calcDist(float x1, float y1, float x2, float y2){
		return Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
	}
}
